#include "fraction.h"

Fraction::Fraction(int num=0,int den=1) throw(DataException): NonComplexNumber(RATIONNAL){
        if(den == 0)
                throw DataException("Division par 0");
        this->num = num;
        this->den = den;
        int d = pgcd(num,den);
        this->num /= d;
        this->den /= d;
this->type = RATIONNAL;
}

Fraction::Fraction(const Integer& c,const Integer&d) throw(DataException): NonComplexNumber(RATIONNAL){

        if(d.getVal() == 0)
                throw DataException("Division par 0");
this->type = RATIONNAL;

        this->num = static_cast<const Integer&>(c).getVal();
        this->den = d.getVal();
        int pgc = pgcd(c.getVal(),d.getVal());
        this->num /= pgc;
        this->den /= pgc;
}

Constante* Fraction::operator+(const Constante& c)const{

        switch(c.getType()){
                case Constante::INTEGER:
        return *this+Fraction(static_cast<const Integer& >(c));
                break;
                case Constante::RATIONNAL:
        return new Fraction(this->num*static_cast<const Fraction&>(c).den+static_cast<const Fraction&>(c).num*this->den,
                        this->den*static_cast<const Fraction&>(c).den);
                break;
        }
        return 0;
}

Constante* Fraction::operator*(const Constante& c)const{
        switch(c.getType()){
                case Constante::INTEGER:
        return *this*Fraction(static_cast<const Integer& >(c));
                break;
                case Constante::RATIONNAL:
        return new Fraction(this->num*static_cast<const Fraction&>(c).num,
                        this->den*static_cast<const Fraction&>(c).den);
                break;
        }
        return 0;
}

Constante* Fraction::operator-(const Constante& c)const{
        switch(c.getType()){
                case Constante::INTEGER:
        return *this-Fraction(static_cast<const Integer& >(c));
                break;
                case Constante::RATIONNAL:
        return new Fraction(this->num*static_cast<const Fraction&>(c).den-static_cast<const Fraction&>(c).num*this->den,
                        this->den*static_cast<const Fraction&>(c).den);
                break;
        }
        return 0;
}

Constante* Fraction::operator/(const Constante& c)const{
        switch(c.getType()){
                case Constante::INTEGER:
        return *this/Fraction(static_cast<const Integer& >(c));
                break;
                case Constante::RATIONNAL:
        return new Fraction(this->num*static_cast<const Fraction&>(c).den,
                        this->den*static_cast<const Fraction&>(c).num);
                break;
        }
        return 0;
}

Constante* Fraction::operator-()const{
        return new Fraction(-this->num,this->den);
}

int pgcd(int a, int b)
{
    int pgcd = 0;

    while(1)
    {
        pgcd = a % b;
        if(pgcd == 0)
        {
            pgcd = b;
            break;
        }
        a = b;
        b = pgcd;
    }

    return pgcd;
}

